package com.cy.pj.common.aspect;

import com.cy.pj.common.annotation.RequiredLog;
import com.cy.pj.common.util.IPUtils;
import com.cy.pj.sys.pojo.SysLog;
import com.cy.pj.sys.service.SysLogService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Date;

//AspectJ是一个面向切面的框架
@Slf4j
@Aspect
@Component
public class SysLogAspect {
    @Pointcut("@annotation(com.cy.pj.common.annotation.RequiredLog)")
    public void doLog(){

    }

    @Around("doLog()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable{
        long t1= System.currentTimeMillis();
        try {
        Object result = joinPoint.proceed();
        long t2=System.currentTimeMillis();
        System.out.println("time:"+(t2-t1));
        saveSysLog((t2-t1), joinPoint);
        return result;
        }catch (Exception e){
            logError(joinPoint,e.getMessage());
            throw e;
        }
    }

    private void logError(ProceedingJoinPoint joinPoint,String exceptionMsg) throws JsonProcessingException {
        String targetClassName=joinPoint.getTarget().getClass().getName();
        String methodName=joinPoint.getSignature().getName();
        String params=new ObjectMapper().writeValueAsString(joinPoint.getArgs());
        log.error("msg->{}->{}-{}",targetClassName+"."+methodName,params,exceptionMsg);
    }

    @Autowired
    private SysLogService sysLogService;

    private void saveSysLog(long time,ProceedingJoinPoint joinPoint) throws NoSuchMethodException, JsonProcessingException {
        //获取对象类型，方法名，参数类型；注解
        Class<?> targetClass=joinPoint.getTarget().getClass();
        MethodSignature s = (MethodSignature) joinPoint.getSignature();
        Method targetMethod=targetClass.getDeclaredMethod(s.getName(),s.getParameterTypes());
        RequiredLog requiredLog=targetMethod.getAnnotation(RequiredLog.class);

        String operation= requiredLog.value();//获取操作名
        SysLog entity=new SysLog();
        entity.setUsername("cgb");
        entity.setCreatedTime(new Date());
        entity.setIp(IPUtils.getIpAddr());
        entity.setTime(time);
        entity.setOperation(operation);
        entity.setMethod(targetClass.getName()+"."+targetMethod.getName());
        entity.setParams(new ObjectMapper().writeValueAsString(joinPoint.getArgs()));
        new Thread(){
            @Override
            public void run(){
                sysLogService.saveObject(entity);
            }
        }.start();
    }
}
